import { Controller, Post, Body, UseGuards, Get, HttpCode, HttpStatus, Request, Logger } from '@nestjs/common'
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger'
import { AuthService } from './auth.service'
import { RegisterDto, LoginDto } from '../common/dto/auth.dto'
import { LocalAuthGuard } from './guards/local-auth.guard'
import { JwtAuthGuard } from './guards/jwt-auth.guard'
import { Public } from './decorators/public.decorator'
import { CurrentUser } from './decorators/current-user.decorator'
import type { AuthUser } from './interfaces/jwt-payload.interface'

/**
 * 认证控制器
 * 处理用户注册、登录、登出等认证相关的HTTP请求
 */
@ApiTags('认证管理')
@Controller('auth')
export class AuthController {
  private readonly logger = new Logger(AuthController.name)

  constructor(private readonly authService: AuthService) {}

  /**
   * 用户注册
   */
  @Public()
  @Post('register')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: '用户注册' })
  @ApiResponse({
    status: 201,
    description: '注册成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '注册成功' },
        data: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            username: { type: 'string' },
            email: { type: 'string' },
            nickname: { type: 'string' },
            role: { type: 'string' },
            createdAt: { type: 'string' }
          }
        }
      }
    }
  })
  @ApiResponse({ status: 400, description: '请求参数错误' })
  @ApiResponse({ status: 409, description: '用户名或邮箱已存在' })
  async register(@Body() registerDto: RegisterDto): Promise<any> {
    try {
      const user = await this.authService.register(registerDto)
      this.logger.log(`用户注册成功: ${registerDto.username}`)

      return {
        success: true,
        message: '注册成功',
        data: user
      }
    } catch (error) {
      this.logger.error(`用户注册失败: ${error.message}`, error.stack)
      throw error
    }
  }

  /**
   * 用户登录
   */
  @Public()
  @UseGuards(LocalAuthGuard)
  @Post('login')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '用户登录' })
  @ApiResponse({
    status: 200,
    description: '登录成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '登录成功' },
        data: {
          type: 'object',
          properties: {
            accessToken: { type: 'string' },
            user: {
              type: 'object',
              properties: {
                id: { type: 'string' },
                username: { type: 'string' },
                email: { type: 'string' },
                nickname: { type: 'string' },
                role: { type: 'string' }
              }
            },
            expiresIn: { type: 'number' }
          }
        }
      }
    }
  })
  @ApiResponse({ status: 401, description: '用户名或密码错误' })
  async login(@Body() loginDto: LoginDto, @Request() req): Promise<any> {
    try {
      const result = await this.authService.login(loginDto)
      this.logger.log(`用户登录成功: ${loginDto.identifier}`)

      return {
        success: true,
        message: '登录成功',
        data: result
      }
    } catch (error) {
      this.logger.error(`用户登录失败: ${error.message}`, error.stack)
      throw error
    }
  }

  /**
   * 获取当前用户信息
   */
  @UseGuards(JwtAuthGuard)
  @Get('profile')
  @ApiBearerAuth()
  @ApiOperation({ summary: '获取当前用户信息' })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '获取成功' },
        data: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            username: { type: 'string' },
            email: { type: 'string' },
            nickname: { type: 'string' },
            role: { type: 'string' },
            avatar: { type: 'string' },
            createdAt: { type: 'string' },
            updatedAt: { type: 'string' }
          }
        }
      }
    }
  })
  @ApiResponse({ status: 401, description: '未授权' })
  async getProfile(@CurrentUser() user: AuthUser) {
    try {
      return {
        success: true,
        message: '获取成功',
        data: user
      }
    } catch (error) {
      this.logger.error(`获取用户信息失败: ${error.message}`, error.stack)
      throw error
    }
  }

  /**
   * 用户登出
   */
  @UseGuards(JwtAuthGuard)
  @Post('logout')
  @HttpCode(HttpStatus.OK)
  @ApiBearerAuth()
  @ApiOperation({ summary: '用户登出' })
  @ApiResponse({
    status: 200,
    description: '登出成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '登出成功' }
      }
    }
  })
  @ApiResponse({ status: 401, description: '未授权' })
  async logout(@Request() req) {
    try {
      const user = req.user
      const sessionId = req.user?.sessionId

      if (sessionId) {
        await this.authService.logout(sessionId)
      }

      this.logger.log(`用户登出成功: ${user?.username}`)

      return {
        success: true,
        message: '登出成功'
      }
    } catch (error) {
      this.logger.error(`用户登出失败: ${error.message}`, error.stack)
      throw error
    }
  }

  /**
   * 刷新Token
   */
  @UseGuards(JwtAuthGuard)
  @Post('refresh')
  @HttpCode(HttpStatus.OK)
  @ApiBearerAuth()
  @ApiOperation({ summary: '刷新Token' })
  @ApiResponse({
    status: 200,
    description: '刷新成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '刷新成功' },
        data: {
          type: 'object',
          properties: {
            accessToken: { type: 'string' },
            expiresIn: { type: 'number' }
          }
        }
      }
    }
  })
  @ApiResponse({ status: 401, description: '未授权' })
  async refreshToken(@CurrentUser() user: AuthUser) {
    try {
      const result = await this.authService.refreshToken(user.id)
      this.logger.log(`Token刷新成功: ${user.username}`)

      return {
        success: true,
        message: '刷新成功',
        data: result
      }
    } catch (error) {
      this.logger.error(`Token刷新失败: ${error.message}`, error.stack)
      throw error
    }
  }
}
